package com.base.library.base

import androidx.lifecycle.viewModelScope
import com.base.library.delegate.ItemViewTypeDelegate
import com.base.library.entity.ItemDataBinding
import com.base.library.ext.send
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch

typealias ListScuCallBack<T> = (list: List<T>?) -> Unit
typealias ListErrorCallBack = (error: Throwable) -> Unit

abstract class BaseListViewModel<T> : BaseVM() {
    val itemDelegate: ItemViewTypeDelegate<T>? by lazy {
        return@lazy createItemDelegate()
    }

    val itemBindingMap by lazy {
        return@lazy createItemBindingMap()
    }

    val mAdapter by lazy {
        return@lazy createAdapter()
    }

    // 加载完成关闭
    val finishRefreshAndLoadMore = MutableSharedFlow<Boolean>()
    var hasMore: Boolean = true
    override fun refresh() {
        viewModelScope.launch {
            refreshData({
                if (!it.isNullOrEmpty()) {
                    hasMore = true
                    showContent()
                } else {
                    showEmpty()
                }
                flushData(it)
                finishRefreshOrLoadMore()
            }, {
                showError()
                finishRefreshOrLoadMore()
            })
        }
    }

    fun loadMore() {
        viewModelScope.launch {
            loadMoreData({
                if (it.isNullOrEmpty()) {
                    hasMore = false
                }
                addItems(it)
                finishRefreshOrLoadMore()
            }, {
                finishRefreshOrLoadMore()
            })
        }
    }

    abstract suspend fun refreshData(
        sucCallback: ListScuCallBack<T>,
        errorCallback: ListErrorCallBack
    )

    abstract suspend fun loadMoreData(
        sucCallback: ListScuCallBack<T>,
        errorCallback: ListErrorCallBack
    )

    /**
     * 通知结束刷新 加载更多
     */
    open fun finishRefreshOrLoadMore() {
        finishRefreshAndLoadMore.send(true)
    }

    open fun createItemDelegate(): ItemViewTypeDelegate<T>? = null

    open fun createItemBindingMap(): Map<Int, ItemDataBinding>? = null

    abstract fun createAdapter(): BaseRecyclerAdapter<T>

    fun flushData(data: Collection<T>?) {
        mAdapter.flushData(data)
    }

    fun addItem(data: T?) {
        mAdapter.addItem(data)
        if (mAdapter.itemCount > 0) {
            showContent()
        }
    }

    fun addItems(dataList: Collection<T>?) {
        mAdapter.addItems(dataList)
        if (mAdapter.itemCount > 0) {
            showContent()
        }
    }

    fun removeItem(data: T?) {
        mAdapter.removeItem(data)
        if (mAdapter.itemCount == 0) {
            showEmpty()
        }
    }

    fun removeItems(dataList: Collection<T>?) {
        mAdapter.removeItems(dataList)
        if (mAdapter.itemCount == 0) {
            showEmpty()
        }
    }
}